<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="text"/>
    <script>
        /*
            闭包是JS中的一种特性，往往用于解决一些特定的问题，当A函数中返回了B函数，并且返回的B函数中有使用到A函数中的局部变量（包含参数)就会形成一个特性的形态，就叫闭包。
            此时，理论上来说A函数执行完成后，生成了B函数后，应该被垃圾回收机制回收，但是因为生成的B函数还在使用A函数中的局部变量,就会导致A函数没有及时回收，导致内存泄露。
        */ 

        /*
            看看下面的代码
            解析：一般来说，一个函数被执行完了，那他以及他里面的变量都会被垃圾回收掉，但是在这里，我们使用c接收到了A执行后返回的B函数，由于c还在引用着B，那么B函数就无法被垃圾回收机制回收，此时B函数里又引用着A函数中的a变量，从而导致a也不能被回收。这样的话就形成了一个闭包的概念，a变量会一直存在在内存中，如果这样的场景多了，就会导致内存泄露。
        */
        function A(){
            let a = 100;
            function B(){
                console.log(a);
            }
            return B;
        }
        let c = A();

        // 闭包的应用场景1：防抖
        function debounce(fun,time){
            let timer = null;
            return function(){//这个内层函数未来会被input框的oninput属性引用，那么里面对于timer的引用导致debounce里的timer不能被回收，从而常驻在内存中。
                if(timer!=null){//如果发现timer不是null，那就代表已经有定时器了，那就先把这个定时器清除，重新给timer赋值一个定时器，定时器里执行fun。如此就形成了只有当你停止当前操作达到一定时长，fun才会执行。这样就减少了性能损耗
                    clearTimeout(timer);
                }
                timer = setTimeout(() => {
                    fun();
                }, time);
            }
        }
        document.querySelector('input').oninput = debounce(function (){
            console.log(document.querySelector('input').value);
        },500);

        // 闭包的应用场景2：节流
        function throttle(fun,time){
            let date = Date.now();//先让date为throttle被触发时候的时间
            return function(){//未来这个内部函数会被window.onresize引用, 一旦窗口大小改变，那就会触发这个函数
                if(Date.now() - date >= time){//如果发现当前时间距离上次记录的date超过了一定时长，那就把date重新赋值为Date.now()并执行fun。这样的话就实现了不管你触发的多么频繁，我一定时间内只会执行一次
                    date = Date.now();
                    fun();
                }
            }
        }
        window.onresize = throttle(function (){
            console.log('窗口大小改变了');
        },1000);
    </script>
</body>
</html>